/**
 * 
 */
package com.fita.wechat.visitor.impl;


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.fita.entity.agent.Agent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.JsonUtils;
import com.fita.entity.car.VehicleCategory;
import com.fita.entity.car.VehicleSize;
import com.fita.entity.coupon.Coupon;
import com.fita.entity.data.Country;
import com.fita.entity.data.CountryCoupon;
import com.fita.entity.data.ExchangeRate;
import com.fita.entity.data.Location;
import com.fita.entity.data.ModelGroup;
import com.fita.entity.data.Supplier;
import com.fita.entity.dto.ehi.response.SpecialEquipment;
import com.fita.entity.order.Order;
import com.fita.entity.order.PayType;
import com.fita.entity.set.Set;
import com.fita.entity.set.SetCategory;
import com.fita.entity.set.SetPayType;
import com.fita.wechat.helper.VehicleHelper;
import com.fita.wechat.service.CountryCouponService;
import com.fita.wechat.service.CountryService;
import com.fita.wechat.service.CouponService;
import com.fita.wechat.service.DataService;
import com.fita.wechat.service.ExchangeRateService;
import com.fita.wechat.service.LocationService;
import com.fita.wechat.service.ModelGroupService;
import com.fita.wechat.service.OrderService;
import com.fita.wechat.service.SetService;

/**
 * 
 * @author mohanlan
 *
 */
@Component("persistentVisitor")
public class PersistentVisitor {
    
    @Autowired
    @Qualifier("dataService")
    private DataService<Supplier> supplierService;
    
    @Autowired
    private CountryService countryService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<SetCategory> setCategoryService;
    
    @Autowired
    private LocationService locationService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<SpecialEquipment> specialEquipmentService;
    
    @Autowired
    private SetService setService;
    
    @Autowired
    private ExchangeRateService exchangeRateService;
    
    @Autowired
    private CountryCouponService countryCouponService;
    
    @Autowired
    private VehicleHelper vehicleHelper;
    
    @Autowired
    private ModelGroupService modelGroupService;
    
    @Autowired
    private CouponService couponService;
    
    @Autowired
    private OrderService orderService;

    @Autowired
    private GenericDaoSupport genericDaoSupport;

    /**
     * 获取代理
     * @param mobile
     * @return
     */
    public Agent loadAgent(String mobile){

        Agent agent = genericDaoSupport.searchForObject("FROM Agent WHERE disabled =false AND mobile = :mobile", "mobile", mobile, Agent.class);

        return agent;
    }

    /**
     * 
     * @return
     */
    public Map<String, Supplier> getSuppliers() {
        
        Map<String, Supplier> result = new HashMap<String, Supplier>();
        
        List<Supplier> suppliers = supplierService.loadAll(Supplier.class);
        result = CollectionUtils.constructMapValue(suppliers, "code");
        
        return result;
    }
    
    /**
     * 
     * @return
     */
    public String getSuppliersJson() {
        Map<String, Supplier> result = this.getSuppliers();
        return JsonUtils.toJson(result);
    }
    
    /**
     * 
     * @return
     */
    public Map<String, List<Country>> getCountries() {
        List<Country> countries = countryService.loadAll(Country.class);
        
        List<Country> resultcountry = new ArrayList<Country>();
        for(Country country : countries) {
            if(country.isValid()) {
                resultcountry.add(country);
            }
        }
        
        Map<String, List<Country>> result = new HashMap<String, List<Country>>();
        
        for(Country country : resultcountry) {
            
            String key = country.getEnglishCode();
            if(result.get(key) == null || result.get(key).isEmpty()) {
                List<Country> items = new ArrayList<Country>();
                items.add(country);
                result.put(key, items);
            } else {
                List<Country> items = result.get(key);
                items.add(country);
                result.put(key, items);
            }
        }
        
        return result;
    }
    
    
    public BigDecimal loadCnyPrice(Long orderId,Long userCouponId) {
    	
    	Order order = orderService.load(orderId);
    	Coupon coupon = couponService.load(userCouponId);

        return order.getCnyPayPrice(coupon.getAmount());
    }
    
    /**
     * 
     * @return
     */
    public Map<String, Map<String, List<Set>>> getSets() {
        
        Map<String, Map<String, List<Set>>> result = new HashMap<String, Map<String, List<Set>>>();
        
        List<Set> sets = setService.listAvaliableSets();
        Map<String, List<Set>> setsMap = CollectionUtils.constructMapValues(sets, "country.code");
        
        for(String key : setsMap.keySet()) {
            List<Set> item = setsMap.get(key);
            Map<String, List<Set>> itemMap = CollectionUtils.constructMapValues(item, "supplier.id");
            result.put(key, itemMap);
        }
        
        return result;
    }
    
    /**
     * 
     * @return
     */
    public Map<String, List<Map<String, String>>> getCities() {
        
        List<Location> locations = locationService.listAll();
        Map<String, List<Location>> locationsMap = CollectionUtils.constructMapValues(locations, "cityName");
        
        Map<String, List<Map<String, String>>> result = new HashMap<String, List<Map<String, String>>>();
        
        for(String cityName : locationsMap.keySet()) {
            String key = cityName.substring(0, 1);
            if(result.get(key) == null || result.get(key).isEmpty()) {
                List<Map<String, String>> items = new ArrayList<Map<String, String>>();
                Map<String, String> params = new HashMap<String, String>();
                params.put("city", cityName);
                params.put("country", locationsMap.get(cityName).get(0).getCountry());
                items.add(params);
                result.put(key, items);
            } else {
                List<Map<String, String>> items = result.get(key);
                Map<String, String> params = new HashMap<String, String>();
                params.put("city", cityName);
                params.put("country", locationsMap.get(cityName).get(0).getCountry());
                items.add(params);
                result.put(key, items);
            }
        }
        
        return result;
    }
    
//    /**
//     * 
//     * @return
//     */
//    public String getLocationsJson() {
//        return JsonUtils.toJson(this.getLocations());
//    }
    
    /**
     * 
     * @return
     */
    public String getSetsJson() {
        Map<String, Map<String, List<Set>>> result = this.getSets();
        return JsonUtils.toJson(result);
    }
    
    /**
     * 
     * @return
     */
    public Map<String, SetCategory> getSetCategories() {
        List<SetCategory> categories = setCategoryService.listAll(SetCategory.class);
        Map<String, SetCategory> result = CollectionUtils.constructMapValue(categories, "id");
        return result;
    }
    
    /**
     * 
     * @return
     */
    public String getSetCategoriesJson() {
        return JsonUtils.toJson(this.getSetCategories());
    }
    /**
     * 
     * @return
     */
    public Map<String, SpecialEquipment> getSpecialEquipments() {
        List<SpecialEquipment> equipments = specialEquipmentService.listAll(SpecialEquipment.class);
        Map<String, SpecialEquipment> result = CollectionUtils.constructMapValue(equipments, "type");
        return result;
    }
    
    /**
     * 
     * @return
     */
    public String getSpecialEquipmentsJson() {
        return JsonUtils.toJson(this.getSpecialEquipments());
    }

    /**
     *
     * @param totalAmount
     * @param payType
     * @param currencyCode
     * @param setPayType
     * @return
     */
    public BigDecimal destinationPaid(BigDecimal totalAmount, PayType payType, String currencyCode, SetPayType setPayType) {
        return vehicleHelper.getDestinationPaid(totalAmount, payType, currencyCode, setPayType);
    }
    
    /**
     * 
     * @param totalAmount
     * @param currencyCode
     * @param rate
     * @return
     */
    public BigDecimal dynamicPrepaid(BigDecimal totalAmount, String currencyCode, int rate, SetPayType setPayType, Integer primaryAgentRate) {
        return vehicleHelper.getDynamicPrepaid(totalAmount, currencyCode, rate, setPayType, primaryAgentRate);
    }

    /**
     *
     * @param totalAmount
     * @param currencyCode
     * @param rate
     * @return
     */
    public BigDecimal dynamicPrepaid(BigDecimal totalAmount, String currencyCode, int rate, SetPayType setPayType) {
        return vehicleHelper.getDynamicPrepaid(totalAmount, currencyCode, rate, setPayType, null);
    }
    
    /**
     * 
     * @param totalAmount
     * @param currencyCode
     * @param rate
     */
    public BigDecimal prepaid(BigDecimal totalAmount, String currencyCode, int rate, Integer primaryAgentRate) {
        return vehicleHelper.getPrepaid(totalAmount, currencyCode, rate, primaryAgentRate);
    }

    public BigDecimal prepaid(BigDecimal totalAmount, String currencyCode, int rate) {
        return vehicleHelper.getPrepaid(totalAmount, currencyCode, rate, null);
    }

    /**
     * 
     * @param totalAmount
     * @param pickupLocationId
     * @param rate
     * @return
     */
    public BigDecimal agentCommission(BigDecimal totalAmount, Long pickupLocationId, int rate) {
        Location location = locationService.load(pickupLocationId);
        Country country = countryService.load(location.getCountry());
        return vehicleHelper.getAgentCommission(totalAmount, country, rate, null);
    }

    /**
     *
     * @param totalAmount
     * @param pickupLocationId
     * @param rate
     * @return
     */
    public BigDecimal agentCommission(BigDecimal totalAmount, Long pickupLocationId, int rate, Integer primaryAgentRate) {
        Location location = locationService.load(pickupLocationId);
        Country country = countryService.load(location.getCountry());
        return vehicleHelper.getAgentCommission(totalAmount, country, rate, primaryAgentRate);
    }
    
    /**
     * 
     * @param countryId
     * @return
     */
    public Country country(Long countryId) {
        return countryService.load(Country.class, countryId);
    }
    
    /**
     * 
     * @param currencyCode
     * @return
     */
    public ExchangeRate exchangeRate(String currencyCode) {
        return exchangeRateService.load(currencyCode, new Date());
    }
    
    /**
     * 
     * @param code
     * @return
     */
    public VehicleCategory getVehicleCategory(String code) {
        return VehicleCategory.codeOf(code);
    }
    
    /**
     * 
     * @param ssip
     * @return
     */
    public VehicleSize getVehicleSize(String ssip) {
        return VehicleSize.ssipOf(ssip);
    }
    
    /**
     * 
     * @param totalAmount
     * @param pickupLocationId
     * @return
     */
    public BigDecimal generateCouponPrice(BigDecimal totalAmount, Long pickupLocationId) {
        Location location = locationService.load(pickupLocationId);
        Country country = countryService.load(location.getCountry());
        CountryCoupon countryCoupon = countryCouponService.load(country, new Date());
        
        if(countryCoupon != null) {
            return totalAmount.multiply(new BigDecimal(countryCoupon.getRate()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP));
        }
        
        return totalAmount;
    }
    
    /**
     * @param englishName
     * @return
     */
    public ModelGroup modelGroup(String englishName) {
        return modelGroupService.load(englishName);
    }
    
    /**
     * @return
     */
    public Map<String, ModelGroup> getModelGroups() {
        List<ModelGroup> modelGroups = modelGroupService.listAll(ModelGroup.class);
        Map<String, ModelGroup> result = CollectionUtils.constructMapValue(modelGroups, "englishName");
        return result;
    }
}
